package no.sachmuld.methodcombination.api.reflection;

import no.sachmuld.methodcombination.api.reflection.component.SimpleMethodCombination;

import java.lang.reflect.Method;
import java.math.BigInteger;

/**
*
*/
public class Sum<T extends Number> extends SimpleMethodCombination<Object, T, T> {

    private T sum;
    private Adder<T> adder;

    public interface Adder <T> {
        T add(T t1, T t2);
    }

    @Override
    public no.sachmuld.methodcombination.api.reflection.Sum<T> build(Class behaviourClass, Method targetMethod) {
        super.build(behaviourClass, targetMethod);
        adder = createAdder(targetMethod.getReturnType());
        return this;
    }

    @Override
    protected boolean handleSingleResult(T singleResult) {
        if (sum == null) {
            sum = singleResult;
        } else {
            sum = adder.add(sum, singleResult);
        }
        return true;
    }

    static private Adder createAdder(Class returnType) {
        if (returnType == Integer.TYPE || returnType == Integer.class) {
            return new Adder<Integer>() {
                @Override
                public Integer add(Integer t1, Integer t2) {
                    return t1 + t2;
                }
            };
        } else if (returnType == BigInteger.class) {
             return new Adder<BigInteger>() {
                @Override
                public BigInteger add(BigInteger t1, BigInteger t2) {
                    return t1.add(t2);
                }
            };
        } else {
            throw new RuntimeException("Unsupported Number type: " + returnType.getName());
        }
    }

    @Override
    protected T combinedResult() {
        return sum;
    }
}
